﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Phone.Controls;

namespace Kiva7.Controls
{
    public class OrientedGrid : Grid
    {

#region Oriented

        public OrientedGrid()
        {
            this.Loaded += OrientedGridLoaded;
        }

        protected PhoneApplicationPage Page
        {
            get
            {
                return GetDependencyObjectFromVisualTree(this, typeof(PhoneApplicationPage)) as PhoneApplicationPage;
            }
        }

        protected DependencyObject GetDependencyObjectFromVisualTree(DependencyObject startObject, Type type)
        {
            DependencyObject parent = startObject;
            while (parent != null)
            {
                if (type.IsInstanceOfType(parent))
                    return parent;
                parent = VisualTreeHelper.GetParent(parent);
            }
            return null;
        }

        protected FrameworkElement FindByName(DependencyObject startObject, string name)
        {
            for(int i=0,
                j = VisualTreeHelper.GetChildrenCount(startObject); 
                i<j; i++)
            {
                DependencyObject dp = VisualTreeHelper.GetChild(startObject, i);
                FrameworkElement fe = dp as FrameworkElement;
                if (fe != null
                    && fe.Name == name)
                {
                    return fe;
                }
                fe = FindByName(dp, name);
                if (fe!= null)
                {
                    return fe;
                }
            }
            return null;
        }

        private void OrientedGridLoaded(object sender, RoutedEventArgs e)
        {
            PhoneApplicationPage page = Page;
            if (page != null)
            {
                ProcessOrientation(page.Orientation);
                page.OrientationChanged += PageOrientationChanged;
            }
        }

        private void PageOrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            ProcessOrientation(e.Orientation);
        }

#endregion

        #region Row

        public static readonly DependencyProperty RowLProperty = DependencyProperty.RegisterAttached(
            "RowL", //Name of the property
            typeof(int?), //Type of the property
            typeof(OrientedGrid), //Type of the provider of the registered attached property
            null); //Callback invoked in case the property value has changed


        public static void SetRowL(DependencyObject obj, int? RowL)
        {
            obj.SetValue(RowLProperty, RowL);
        }

        public static int? GetRowL(DependencyObject obj)
        {
            return (int?)obj.GetValue(RowLProperty);
        }


        public static readonly DependencyProperty RowPProperty = DependencyProperty.RegisterAttached(
    "RowP ", //Name of the property
    typeof(int?), //Type of the property
    typeof(OrientedGrid), //Type of the provider of the registered attached property
    null); //Callback invoked in case the property value has changed


        public static void SetRowP(DependencyObject obj, int? RowP)
        {
            obj.SetValue(RowPProperty, RowP);
        }

        public static int? GetRowP(DependencyObject obj)
        {
            return (int?)obj.GetValue(RowPProperty);
        }

        #endregion

        #region Column

        public static readonly DependencyProperty ColumnLProperty = DependencyProperty.RegisterAttached(
            "ColumnL", //Name of the property
            typeof(int?), //Type of the property
            typeof(OrientedGrid), //Type of the provider of the registered attached property
            null); //Callback invoked in case the property value has changed


        public static void SetColumnL(DependencyObject obj, int? ColumnL)
        {
            obj.SetValue(ColumnLProperty, ColumnL);
        }

        public static int? GetColumnL(DependencyObject obj)
        {
            return (int?)obj.GetValue(ColumnLProperty);
        }


        public static readonly DependencyProperty ColumnPProperty = DependencyProperty.RegisterAttached(
    "ColumnP ", //Name of the property
    typeof(int?), //Type of the property
    typeof(OrientedGrid), //Type of the provider of the registered attached property
    null); //Callback invoked in case the property value has changed


        public static void SetColumnP(DependencyObject obj, int? ColumnP)
        {
            obj.SetValue(ColumnPProperty, ColumnP);
        }

        public static int? GetColumnP(DependencyObject obj)
        {
            return (int?)obj.GetValue(ColumnPProperty);
        }

        #endregion

        #region Visibility

        public static readonly DependencyProperty VisibilityLProperty = DependencyProperty.RegisterAttached(
            "VisibilityL", //Name of the property
            typeof(Visibility?), //Type of the property
            typeof(OrientedGrid), //Type of the provider of the registered attached property
            null); //Callback invoked in case the property value has changed


        public static void SetVisibilityL(DependencyObject obj, Visibility? visibilityL)
        {
            obj.SetValue(VisibilityLProperty, visibilityL);
        }

        public static Visibility? GetVisibilityL(DependencyObject obj)
        {
            return (Visibility?)obj.GetValue(VisibilityLProperty);
        }


        public static readonly DependencyProperty VisibilityPProperty = DependencyProperty.RegisterAttached(
    "VisibilityP ", //Name of the property
    typeof(Visibility?), //Type of the property
    typeof(OrientedGrid), //Type of the provider of the registered attached property
    null); //Callback invoked in case the property value has changed


        public static void SetVisibilityP(DependencyObject obj, Visibility? visibilityP)
        {
            obj.SetValue(VisibilityPProperty, visibilityP);
        }

        public static Visibility? GetVisibilityP(DependencyObject obj)
        {
            return (Visibility?)obj.GetValue(VisibilityPProperty);
        }

        #endregion


        #region Process

        //Just a sample method ilustrating the idea how to obtain the value

        private void ProcessOrientation(PageOrientation orientation)
        {
            foreach (UIElement element in Children)
            {
                ProcessOrientation(element as FrameworkElement, orientation);
            }
            
        }

        private void ProcessOrientation(FrameworkElement control, PageOrientation orientation)
        {
            if (control == null)
            {
                return;
            }
            if ((orientation & PageOrientation.Landscape) == PageOrientation.Landscape)
            {
                SetAsLandscape(control);
            }
            else
            {
                SetAsPortrait(control);
            }
        }

        private static void SetAsPortrait(FrameworkElement control)
        {
            int? RowP = OrientedGrid.GetRowP(control);
            if (RowP.HasValue)
            {
                Grid.SetRow(control, RowP.Value);
            }

            int? ColumnP = OrientedGrid.GetColumnP(control);
            if (ColumnP.HasValue)
            {
                Grid.SetColumn(control, ColumnP.Value);
            }

            Visibility? VisibilityP = OrientedGrid.GetVisibilityP(control);
            if (VisibilityP.HasValue)
            {
                control.Visibility = VisibilityP.Value;
            }

        }

        private static void SetAsLandscape(FrameworkElement control)
        {
            int? RowL = OrientedGrid.GetRowL(control);
            if (RowL.HasValue)
            {
                Grid.SetRow(control, RowL.Value);
            }

            int? ColumnL = OrientedGrid.GetColumnL(control);
            if (ColumnL.HasValue)
            {
                Grid.SetColumn(control, ColumnL.Value);
            }

            Visibility? visibility = OrientedGrid.GetVisibilityL(control);
            if (visibility.HasValue)
            {
                control.Visibility = visibility.Value;
            }

        }

        #endregion
    }
}
